#!/usr/bin/python
#-*-coding: utf-8 -*- 
# Roxane Levy

import ctypes
from numpy import genfromtxt,array,linalg,zeros,apply_along_axis,nditer,sqrt,unravel_index
from pylab import plot,axis,show,pcolor,colorbar,bone
  
LIBRARY_PATH = './som.so'


def distance_map(weights):
        distance_map = zeros((weights.shape[0],weights.shape[1]))
        it = nditer(um, flags=['multi_index'])
        while not it.finished:
            for ii in range(it.multi_index[0]-1,it.multi_index[0]+2):
                for jj in range(it.multi_index[1]-1,it.multi_index[1]+2):
                    if ii >= 0 and ii < weights.shape[0] and jj >= 0 and jj < weights.shape[1]:
                        distance_map[it.multi_index] += linalg.norm(weights[ii,jj,:]-weights[it.multi_index])
            it.iternext()
        distance_map = distance_map/distance_map.max()
        return distance_map




def findbestmatchingnode(vector,weights,activation_map) :
      for a in range(len(weights)) : 
	   for b in range(len(weights[a])) : 
		activation_map[a][b] = linalg.norm(euclidian(weights[a][b],vector))
      return unravel_index(activation_map.argmin(),
activation_map.shape) 



def euclidian(vectorMap, vectorData) :
	""" Fonction qui retourne la distance euclidienne entre deux vecteurs """
	distance = 0 
        for i in range(len(vectorMap)) :
 		distance += (vectorData[i] - vectorMap[i]) * (vectorData[i] - vectorMap[i])
	dist = sqrt(distance)
	return dist



  
def main():
    '''Main entry point.'''
    numberInputVec = 150
    neuroneSize = 4 
    
    map_x = 10
    map_y = 8

    nb_iter  = 2000 
    
    # Load the library
    my_library = ctypes.CDLL(LIBRARY_PATH)

    my_library.startprog.argtypes = [ctypes.c_int, ctypes.c_int,ctypes.c_int,ctypes.c_int,ctypes.c_int]
    my_library.main.argtypes = []  
    my_library.getData.argtypes = []
    my_library.getRN.argtypes = []
    my_library.getActiMap.argtypes = []
    

    my_library.startprog.restype = ctypes.c_int
    my_library.main.restype = ctypes.c_int   # toujours vérifier que le main du prog C retourne 0
    my_library.getData.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_float *neuroneSize) * numberInputVec)   # recevoir les vecteurs de données
    my_library.getRN.restype = ctypes.POINTER(ctypes.POINTER(ctypes.POINTER(ctypes.c_float * neuroneSize) * map_y ) * map_x )
    my_library.getActiMap.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_float * map_y) * map_x)
    my_library.destroyAll.restype = ctypes.c_int

  
  
    init = my_library.startprog(numberInputVec,neuroneSize,map_x,map_y, nb_iter)
    print 'init returns : ', init

    main_result = my_library.main()
    print 'Main ends : ',main_result 
  
    c_array = my_library.getData()

    
    data = zeros((numberInputVec,neuroneSize))
    index = 0 
    row = 0
    for i in c_array.contents : 
	for j in i.contents : 
		data[index][row] = j
		row += 1
	index +=1
        row = 0


    print 'data done\n'
    
    e_array = my_library.getRN() 

    index1 = 0
    index2=0
    index3 = 0
 
    weights = zeros((map_x,map_y,neuroneSize))
    for i in e_array.contents :
	for j in i.contents :
                for k in j.contents :
			weights[index1][index2][index3] = k
			index3+= 1
		index2 += 1
		index3 = 0 
        index1 += 1
        index2 = 0

    print 'weights python done\n'

    f_array = my_library.getActiMap()
    activation_map = zeros((map_x,map_y))
    index = 0 
    row = 0
    for i in f_array.contents : 
	for j in i.contents : 
		activation_map[index][row] = j
		row += 1
	index +=1
        row = 0

    print 'activation map done\n'

### Plotting the response for each pattern in the iris dataset ###

    bone()
    pcolor(distance_map(weights).T) # plotting the distance map as background  , .T is for transposing the matrix
    colorbar()
    target = genfromtxt('iris.csv',delimiter=',',usecols=(4),dtype=str) # loading the labels
    t = zeros(len(target),dtype=int)
    t[target == 'Iris-setosa'] = 0
    t[target == 'Iris-versicolor'] = 1
    t[target == 'Iris-virginica'] = 2
    # use different colors and markers for each label
    markers = ['o','s','D']
    colors = ['r','g','b']
    
    for cnt,xx in enumerate(data):   #cnt is the idex of input vector used, xx is the vector we want to input
 	w = findbestmatchingnode(xx,weights,activation_map) # getting the winner
 	# palce a marker on the winning position for the sample xx
 	plot(w[0]+.5,w[1]+.5,markers[t[cnt]],markerfacecolor='None',markeredgecolor=colors[t[cnt]],markersize=12,markeredgewidth=2)

    axis([0,weights.shape[0],0,weights.shape[1]])
    show() 
   

    erase = my_library.destroyAll()
    print "erase :",erase


if __name__ == '__main__':
    main()
